package eu.gegenleitner.esspacc.gui;

import java.awt.Desktop;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.utils.Base64;

import eu.gegenleitner.esspacc.communication.Messages;

public class RunnableTokenSender implements Runnable {

	private MainWindow mainWindow;
	
	public RunnableTokenSender(MainWindow window) {
		mainWindow = window;
	}
	
	public void run() {
		try {
			mainWindow.getBtnSubmitToken().setEnabled(false);
			mainWindow.addLineToUserInfo("Send Token to Service\t\t\t\t", true);
			/*TODO: InputValidation*/
			String token = mainWindow.getTokenTextField().getText();
			String response = mainWindow.hReq.sendTokenFromEMail(token);
			if( response.equals(Messages.tokenInvalid) )
				throw new Exception(response);
			mainWindow.addLineToUserInfo("[DONE]", false);
			mainWindow.addLineToUserInfo("Store Certificate and Private Key\t\t", true);
			storeCertificate(response, mainWindow.keyPair);
			mainWindow.addLineToUserInfo("[DONE]", false);
			JOptionPane.showMessageDialog(null, "Certificate and PrivateKey stored successfully!");
			mainWindow.endProgramm();
		} catch(Exception e) {
			e.printStackTrace();
			mainWindow.addLineToUserInfo("[ERROR]", false);
			mainWindow.addLineToUserInfo(e.getMessage(), true);
		}
		
	}

	private void storeCertificate(String response, KeyPair keyPair) throws CertificateException,
																			Base64DecodingException,
																			InvalidKeyException,
																			NoSuchAlgorithmException,
																			NoSuchProviderException,
																			SignatureException,
																			KeyStoreException,
																			IOException {
		CertificateFactory certFact = CertificateFactory.getInstance("X509");
		
		// Parse caCert and newCert
		String caCertBase64 = response.substring(response.indexOf("<caCert>") + "<caCert>".length(), response.indexOf("</caCert>"));
		String newCertBase64 = response.substring(response.indexOf("<newCert>") + "<newCert>".length(), response.indexOf("</newCert>"));
		X509Certificate newCert = (X509Certificate)certFact.generateCertificate(new ByteArrayInputStream(Base64.decode(newCertBase64)));
		X509Certificate caCert = (X509Certificate)certFact.generateCertificate(new ByteArrayInputStream(Base64.decode(caCertBase64)));
		
		newCert.verify(caCert.getPublicKey());
		newCert.checkValidity();
		
		JFileChooser fileChooser = new JFileChooser();
		FileNameExtensionFilter filter = new FileNameExtensionFilter("PKCS12 File", "p12");
		fileChooser.setFileFilter(filter);
		if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
			File file = fileChooser.getSelectedFile();
			KeyStore store = KeyStore.getInstance("PKCS12");
			store.load(null, null);
			
			X509Certificate[] chain = new X509Certificate[2];
			// First the client, then the CA certificate
			chain[0] = newCert;
			chain[1] = caCert;
			
			store.setKeyEntry("ESSPACC Client-Certificate", keyPair.getPrivate(), "".toCharArray(), chain);
			
			FileOutputStream fOut = new FileOutputStream(file);
			store.store(fOut, "".toCharArray());
			fOut.flush();
			fOut.close();
			Desktop.getDesktop().open(new File(file.getAbsolutePath().replaceAll(file.getName(), "")));
		}
	}

}
